import 'dart:async';

import 'package:get/get.dart';

// ignore: avoid_types_as_parameter_names
abstract class MVIViewModel<State, Event, Effect> extends GetxController {
  late Rx<State> _state;

  State get state => _state.value;

  State get initialState;

  final StreamController<Event> _eventChannel = StreamController.broadcast();
  final StreamController<Effect> _sideEffectChannel =
      StreamController.broadcast();

  Stream<Effect> get sideEffectFlow => _sideEffectChannel.stream;

  void handleEvent(Event event);

  void sendEvent(Event event) {
    if (!_eventChannel.isClosed) {
      _eventChannel.add(event);
    }
  }

  void sendEffect(Effect effect) {
    if (!_sideEffectChannel.isClosed) {
      _sideEffectChannel.add(effect);
    }
  }

  void updateState(State newState) {
    _state.value = newState;
  }

  @override
  void onInit() {
    super.onInit();
    _state = Rx(initialState);
    _processEvents();
  }

  void _processEvents() {
    _eventChannel.stream.listen((event) {
      handleEvent(event);
    });
  }

  @override
  void onClose() {
    _eventChannel.close();
    _sideEffectChannel.close();
    super.onClose();
  }
}
